
package com.feib.ebilling.job;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

import com.feib.ebilling.job.service.BankingFeedbackCheckService;
import com.feib.ebilling.job.service.BankingFeedbackService;
import com.feib.ebilling.job.service.FtpService;
import com.feib.ebilling.job.service.MqService;
import com.feib.ebilling.job.util.StringUtils;


/**
 * @title (#)BankingFeedbackCheck.java<br>
 * @description 銀行代收通路銷帳回饋批次檢核<br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/12/11 create by Jimmy Liu<br>
 */
@Service("bankingFeedbackCheck")
public class BankingFeedbackCheck {

    public static Logger logger = LoggerFactory.getLogger(BankingFeedbackCheck.class);

    public static final SimpleDateFormat BASIC_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    
    private static ApplicationContext ctx;

    @Resource(name="bankingFeedbackCheckService")
    private BankingFeedbackCheckService bankingFeedbackCheckService;

    @Resource(name="bankingFeedbackService")
    private BankingFeedbackService bankingFeedbackService;
 

    @Resource(name="ftpService")
    private FtpService ftpService;

    @Resource(name="batchProperties")
    private Properties batchProperties;

    private static String localFolderProperty="C:\\ebilling\\download"; 

    /**
     * @param args
     */
    public static void main(String[] args) {

        BankingFeedbackCheck.ctx = new ClassPathXmlApplicationContext(
                        new String[] {"applicationContext-config.xml", "applicationContext-dao.xml", "applicationContext-properties.xml"});

        Date start = new Date();
        logger.info("[開始] 銀行代收通路銷帳回饋批次檢核  - {}", BASIC_DATE_TIME_FORMAT.format(start));
        try {
            BankingFeedbackCheck bankingFeedbackCheck = (BankingFeedbackCheck)BankingFeedbackCheck.ctx.getBean("bankingFeedbackCheck");

            /* 前一交易日全部的資料驗證  */
            String sSystemDate = StringUtils.PadString("R", "0", 7, StringUtils.GetStrCDate());
            logger.info("目前系統日 ：{}", sSystemDate);
            sSystemDate = StringUtils.GetStrCDateDiff(sSystemDate, -1);
            sSystemDate = StringUtils.PadString("R", "0", 7, sSystemDate);
            logger.info("前一交易日 ：{}", sSystemDate);

            if (args.length==0){
                // do nothing
            }
            else
            {
                /* 執行指定日期、時間檔案 */  
                sSystemDate = args[0];
                logger.info("檢核交易日 ：", sSystemDate);
            }

            //if (bankingFeedbackCheck.doCheck(sSystemDate, "00000000", "23595999")){
                /* 備份昨日資料至YYYYMMDD目錄 */
            	File dir = new File(localFolderProperty + "\\" + sSystemDate);
            	if (!dir.exists()) {    
            	    dir.mkdir(); 
            	    logger.info("[執行]建立{}備份目錄 ",localFolderProperty + "\\" + sSystemDate);
            	} 
            	File dirList = new File(localFolderProperty);
            	File list[] = dirList.listFiles();
            	boolean fileZeroCnt = false;
            	for(int i=0;i<list.length;i++){   
            		if(list[i].isFile() && 
            		  (list[i].getName().indexOf(sSystemDate) > 0 ||
            		   list[i].getName().indexOf(StringUtils.ConvCDate2EDate(sSystemDate)) > 0) ){
            		   File	sourceFile = new File(localFolderProperty + "\\" + list[i].getName());
            		   File targetFile = new File(localFolderProperty + "\\" + sSystemDate + "\\" + list[i].getName());
            		   if (targetFile.exists()){
            			   /* 備份檔案已存在先刪除 */
            			   targetFile.delete();
            			   logger.info("[執行]刪除{}原備份檔案 ",localFolderProperty + "\\" + sSystemDate + "\\" + list[i].getName());
            		   } 
            		   fileZeroCnt = false;
            		   /* 因為筆數檔為零的明細檔不會下載處理，因此要判斷將FTP Server檔案刪除 */
            		   if (list[i].getName().substring(0,3).equals("VC_") && 
            			   list[i].getName().indexOf("_CNT") > 0){
            			   BufferedReader in = new BufferedReader(new FileReader(sourceFile));
                           String str = null;                                                               
                           while ((str = in.readLine()) != null) {
                               /* 檔案總筆數 */ 
                               if (str.substring(0,8).trim().equals("00000000")){
                            	   fileZeroCnt = true;
                            	   logger.info("筆數檔為零:{}", sourceFile.getName());
                               }
                           }
                           in.close();
            		   } 
            		   dir = new File(localFolderProperty + "\\" + sSystemDate);
            		   boolean success = sourceFile.renameTo(new File(dir, sourceFile.getName()));
            		   if (!success) {
            			   logger.error("[備份檔案{}失敗]", sourceFile.getName());
            		   }else{
            			   logger.info("[備份檔案{}成功]", sourceFile.getName());
            			   /* FTP檔案刪除 */
            			   if (list[i].getName().substring(0,3).equals("VC_")){
            				   if (bankingFeedbackCheck.deleteFTPfile(list[i].getName())){
            					   logger.info("[執行]刪除{}FTP檔案成功", list[i].getName());
            					   if (fileZeroCnt){
            						   /* 筆數檔為零，FTP Server明細檔案刪除 */
            						   String tempfilename = list[i].getName().substring(0,list[i].getName().length() - 8) 
            						                         + ".TXT";
            						   if (bankingFeedbackCheck.deleteFTPfile(tempfilename)){
                    					   logger.info("[執行]刪除{}FTP檔案成功", tempfilename); 
            						   }else{
            							   logger.info("[執行]刪除{}FTP檔案失敗 ", tempfilename);
            						   }
            					   }
            				   }else{
            					   logger.info("[執行]刪除{}FTP檔案失敗 ", list[i].getName());
            				   }
            			   }
            		   }
            		}
            	}
            	logger.info("[完成]備份目錄{} ",localFolderProperty + "\\" + sSystemDate);
            //}
        }
        catch (Exception e) {
            logger.error("[錯誤]" + e.getMessage(), e);
        }
        finally{
            Date end = new Date();
            logger.info("[結束] 銀行代收通路銷帳回饋批次檢核  - {}", BASIC_DATE_TIME_FORMAT.format(start));
            logger.info("共費時 - " + ((end.getTime() - start.getTime()) / 1000) + " 秒");
        }

    }
    
    public boolean deleteFTPfile(String sFileName){
    	return ftpService.delFTPFile("FEIB", sFileName, 1);
    }
    /**
     * 取得檔案並新增至虛擬帳號銷帳日誌
     * @param sSystemDate 日期
     * @param sSystemTime_Begin 時間區間起
     * @param sSystemTime_End 時間區間迄
     * @return 成功(True)或是敗(False)
     */
    public boolean doCheck(String sSystemDate, String sSystemTime_Begin, String sSystemTime_End){
        try{

            /* 取得資料庫所有「虛擬帳號」對映之「實體帳號」 */
            HashMap<String, Integer> hmAccount = new HashMap<String, Integer>();
            List<Map<String, Object>> rds = bankingFeedbackService.getRealAccounts();
            for(Map<String, Object> rd: rds)
            {
                String sAcctID = ((String)rd.get("ACCOUNT_NO")).trim();
                if (! hmAccount.containsKey(sAcctID)){
                    hmAccount.put(sAcctID, new Integer(1));
                    logger.info("「{}」 虛擬帳號入帳實體帳號：{}", ((String)rd.get("GROUP_NAME")),  sAcctID);
                }
            }

            boolean bRtn = true;
            String cnt = "";

            /* 執行送優利電文  */
            if (sendRequest(sSystemDate, sSystemTime_Begin, sSystemTime_End)){

                String waitForFtpFileProperty = batchProperties.getProperty("WaitForFtpFileCheck");
                localFolderProperty = batchProperties.getProperty("LocalFolder");

                logger.info("Wait for UniSys File {} ms", waitForFtpFileProperty); 
                /* 等優利產生檔案 */
                Thread.sleep(Long.parseLong(waitForFtpFileProperty));

                /* FTP 取得銷帳筆數檔 */
                String sFileName = "VC_" + sSystemDate + "_" + sSystemTime_Begin + "_" + sSystemTime_End + "_CNT.TXT";                

                if (ftpService.retryGetFtpFile("FEIB", sFileName)){
                    /* 檢核檔案是否已產生  */                                
                    File ftpFile = new File(localFolderProperty + "\\" + sFileName);
                    if(ftpFile.exists()){
                        logger.info("Read file : {}", ftpFile.getAbsolutePath());

                        BufferedReader in = new BufferedReader(new FileReader(ftpFile));
                        String str = null;                                                               
                        while ((str = in.readLine()) != null) {
                            /* 檔案總筆數 */ 
                            cnt = str.substring(0,8).trim();
                            logger.info("銷帳筆數檔 ：{}", cnt );
                        }
                        in.close();
                    }else{
                        /* 無下載檔案資料 */        
                        logger.error("[錯誤]Open {} failed.", sFileName);
                        bRtn = false;
                    }
                }else{
                    /* FTP 取檔失敗 */       
                    logger.error("[錯誤]Get Ftp file {} failed", sFileName);
                    bRtn = false; 
                }

                /* FTP 取得銷帳明細檔 */
                sFileName = "VC_" + sSystemDate + "_" + sSystemTime_Begin + "_" + sSystemTime_End + ".TXT";

                /* 如果第一個檔案下載失敗，第二個檔案就不下載了。 */
                if (bRtn == true && !"00000000".equals(cnt) &&
                                ftpService.retryGetFtpFile("FEIB", sFileName) ){
                    /* 檢核檔案是否已銷帳  */
                    File ftpFile = new File(localFolderProperty + "\\" + sFileName);
                    if(ftpFile.exists()){
                        logger.info("Read file : {}", ftpFile.getAbsolutePath());
                        BufferedReader in = new BufferedReader(new FileReader(ftpFile));
                        String str = null;
                        long totalcount = 0; 
                        long totalend = 0; 
                        while ((str = in.readLine()) != null) { 
                            totalend++;
                            /* 實體帳號 */   
                            String realAccount = str.substring(0,14).trim();                                       
                            if (hmAccount.get(realAccount) != null){
                                /* 實體帳號要入帳在系統有登記 */
                                totalcount++; 
                            }
                        } 
                        in.close();
                        if (totalend == Long.parseLong(cnt)){

                            /* 確認前一天回饋的筆數正確 */

                            /* 資料庫中前一天回饋筆數 */
                            totalend = this.bankingFeedbackCheckService.countByFbfileName(sFileName.substring(0, 10));

                            if (totalend == totalcount){
                                logger.info("當日銷帳筆數相符： " + totalcount);                                                           
                            }else{
                                logger.error("[錯誤]資料庫銷帳資料筆數：{}", totalend);
                                logger.error("[錯誤]銷帳明細檔筆數：{}", totalcount);
                                logger.error("[錯誤]當日回饋筆數不符，請人工檢核...");
                            }                                                                       
                        }else{
                            /* 檔案筆數檔與明細檔不符 */
                            logger.error("[錯誤]銷帳筆數檔：{}", Long.parseLong(cnt));
                            logger.error("[錯誤]銷帳明細檔：{}", totalend);
                            logger.error("[錯誤]檔案筆數與明細筆數不符，請人工檢核...");
                        } 
                    }else{                             
                        /* Local 讀檔失敗 */
                        logger.error("[錯誤]Open failed.", sFileName);
                        bRtn = false;
                    }
                }else{                                       
                    if ("00000000".equals(cnt)){
                        logger.info("無銷帳資料可回饋");
                        bRtn = true;
                    }else{
                        /* FTP 取檔失敗 */
                        logger.error("[錯誤]Get Ftp file {} failed.", sFileName);
                        bRtn = false;
                    }
                }    
            }else{
                /* MQ 送電文失敗 */   
                logger.error("[錯誤]送優利MQ電文failed ");
                bRtn = false; 
            }
            return bRtn;
        }catch (Exception ex){
            logger.error("[錯誤]" + ex.toString(), ex);
            return false;
        }
    }


    public boolean sendRequest(String sDate,String sTimeBegin, String sTimeEnd) {

        try{
            
            MqService mqService = (MqService)ctx.getBean("mqService");

            /* 遠銀虛擬帳號入帳明細查詢電文 --> 通知優利產生檔案 */ 
            logger.info("SendMQ starting...");
            String cdate = StringUtils.GetStrCDate();
            if (cdate.length() > 6)
                cdate = cdate.substring(1, 7);
            String myTITA = "  " + mqService.getMyTITA().substring(0,3) + cdate + mqService.getMyTITA().substring(9, mqService.getMyTITA().length());


            /* 交易日 */
            myTITA += sDate;
            /* 交易時間起點(含) */
            myTITA += sTimeBegin;
            /* 交易時間終點(含) */
            myTITA += sTimeEnd;  

            mqService.setMyTITA(myTITA);

            if ("1".equals(MqService.MQonline))  {
                /* MQ Online */ 
                mqService.send(myTITA, MqService.MSG_TYPE_NONEXML, mqService.getMyMessageID(), "");
            }else{  
                /* Fake MQ 模擬電文 */
                mqService.send(myTITA, MqService.MSG_TYPE_NONEXML, mqService.getMyMessageID(), "TOTA.txt");
            }

            String totaStr = mqService.rcv(mqService.getMyMessageID());

            if (totaStr != null && totaStr.length() >= 19)
                logger.info("SendMQ Result=" + totaStr.substring(15,19));     
            if (totaStr.indexOf("G001") < 0){
                return false;
            }
            return true;

        }catch (Exception ex){
            logger.error("[錯誤]"+ex.toString(), ex);
            return false;
        }
    } 

}
